<?

class Smutty_Controller {

	var $_viewData = array();

	// this variable is used to enable the scaffolding
	var $scaffold = false;

	/**
	 *  returns the name of the default model class
	 *  to use for the current controller.
	 *
	 *  @return String the model name
	 *
	 */

	function _getModelClass() {
		if ( isset($this->modelName) )
			return $this->modelName;
		else {
			$class = preg_replace( '/Controller/i', '', ucfirst(get_class($this)) );
			if ( file_exists("application/models/$class.php") )
				return $class;
			else
				return false;
		}
	}

	/**
	 *  shows the view file using the specified template class
	 *
	 *  @param [viewFile] path to view file
	 *  @param [template] instance of templace class to use
	 *
	 */

	function _view( $viewFile, $template ) {
		foreach ( $this->_viewData as $key => $value )
			$template->assign( $key, $value );
		$template->display( $viewFile );
	}

	/**
	 *  show the view file using the smutty template class
	 *
	 *  @param [viewFile] the file to view
	 *
	 */

	function _viewSmut( $viewFile ) {
		$this->_viewData['modelName'] = $this->_getModelClass();
		$this->_view( $viewFile, new Smutty_Template_Smutty() );
	}

	/**
	 *  show the specified file with the standard user
	 *  template class.  if the view file is not specifed
	 *  then it is assumed to be located as "views/controller/action.tpl"
	 *
	 *  @param [viewFile] the file to view
	 *
	 */

	function view( $viewFile = false ) {
		if ( !$viewFile ) {
			$router = Smutty_Router::getInstance();
			$viewFile = $router->getActionName() . '.tpl';
		}
		$this->_view( $viewFile, new Smutty_Template() );
	}

	/**
	 *  sets a variable for use by the template
	 *
	 *  @param [name] name of the variable to set
	 *  @param [value] the value to set
	 *
	 */

	function set( $name, $value ) {
		$this->_viewData[ $name ] = $value;
	}

	/**
	 *  redirects the user to the given url.  the parameter array
	 *  should be a hash and accepts the following values.
	 *
	 *    controller => name of controller
	 *    action => action on controller
	 *    id => id to pass to action
	 *
	 *  @param [params] array of parameters
	 *
	 */

	function redirect( $params ) {
		header( 'Location: ' . Smutty_Utils::getUrl($params) );
		exit();
	}

	/**
	 *  this function takes the same arguments as the normal
	 *  redirect function, but prints out javascript code
	 *  to do the redirect itself.  this can be useful when
	 *  doing ajax callbacks with forms.
	 *
	 *  it would be nice if i could think of a way to merge these
	 *  two methods and have it "know" which one to do, but that
	 *  seems a bit impossible i think?
	 *
	 *  @param [params] params for the redirect
	 *
	 */

	function redirectJs( $params ) {
		$url = Smutty_Utils::getUrl( $params );
		echo '<script type="text/javascript">self.location.href=\'' . $url . '\';</script>';
		exit();
	}

	/**
	 *  these are the scaffold methods that can be overridden by
	 *  the child class
	 *
	 */

	/**
	 *  the index action tries to display a table of data
	 *  for the records for this controllers default model
	 *
	 */

	function indexAction() {

		if ( !$this->scaffold )
			new Smutty_Exception( ERR_ACTION_INVALID, 'ClassSmutty_Controller' );

		$modelClass = $this->_getModelClass();

		if ( $modelClass ) {

			eval( "\$models = $modelClass::fetchAll();" );
			eval( "\$fields = $modelClass::getFields();" );
	
			$this->set( 'fields', $fields );
			$this->set( 'models', $models );

		}

		$this->_viewSmut( 'scaffold/index.tpl' );

	}

	/**
	 *  this action tries to show a specific record
	 *
	 */

	function showAction( $data ) {

		if ( !$this->scaffold )
			new Smutty_Exception( ERR_ACTION_INVALID, 'ClassSmutty_Controller' );

		$id = $data->int( 'id' );
		$modelClass = $this->_getModelClass();

		if ( $modelClass ) {
			eval( "\$model = $modelClass::find( \$id );" );	
			$this->set( 'model', $model );
		}

		$this->_viewSmut( 'scaffold/show.tpl' );

	}

	/**
	 *  this action shows the edit form, if an id is specified
	 *  then it tries to fill the form with that records data
	 *
	 */

	function editAction( $data ) {

		if ( !$this->scaffold )
			new Smutty_Exception( ERR_ACTION_INVALID, 'ClassSmutty_Controller' );

		$id = $data->int( 'id' );
		$modelClass = $this->_getModelClass();

		if ( $modelClass ) {

			eval( "\$model = $modelClass::find( \$id );" );
			eval( "\$fields = $modelClass::getFields();" );
		
			$this->set( 'model', $model );
			$this->set( 'fields', $fields );

		}

		$this->_viewSmut( 'scaffold/edit.tpl' );

	}

	/**
	 *  this saves the a record if it exists, or creates a new
	 *  one if it doesn't.  then redirects the user back to
	 *  it's "show" page.
	 *
	 */

	function saveAction( $data ) {

		if ( !$this->scaffold )
			new Smutty_Exception( ERR_ACTION_INVALID, 'ClassSmutty_Controller' );

		$id = $data->int( 'id' );
		$modelClass = $this->_getModelClass();
		eval( "\$model = $modelClass::find($id);" );
		if ( !$model )
			$model = new $modelClass();
		eval( "\$fields = $modelClass::getFields();" );

		foreach ( $fields as $field ) {
			$name = $field->name;
			if ( $name == 'id' )
				continue;
			$value = '';
			switch ( $field->type ) {
				case 'int':
					$value = $data->int( $name );
					break;
				case 'datetime':
					$value = $data->int("dy_$field->name") . '-' .
						$data->intPad("dm_$field->name") . '-' .
						$data->intPad("dd_$field->name");
					break;
				default:
					$value = $data->string( $name );
			}
			$model->$name = $value;
		}

		// try and save the model, if all goes well then
		// redirect the user to it's "show" page
		if ( $model->save() )
			$this->redirect(array(
				action => 'show',
				id => $model->id
			));

	}

}

?>